﻿using PlcLib.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PlcLib.Model
{
    /// <summary>
    /// 欧姆龙读写返回结果实体
    /// </summary>
    public class OrmonResult : IPlcResult
    {
        public Command Command { get;  set; }

        public object Content { get; set; }

        public bool Sucess { get; set; }

        public string Message { get; set; }

        public Exception Exception { get; set; }
        public byte[] ReceiveBuffer { get; set; }
    }

    /// <summary>
    /// 欧姆龙读写返回结果实体
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class OrmonResult<T> : IPlcResult<T>
    {
        public Command Command { get; set; }

        /// <summary>
        /// 返回数据bool,short,short[],int,int[],float,float[],unshort,unshort[],string等
        /// </summary>
        public T Content
        {
            get
            {
                object result = new object();
             
                if(RealByteArray.Length == 0)
                {
                    return default;
                }
              
                var type = typeof(T);
                switch (type.FullName)//获取类型的全民
                {
                    //单个变量
                    case "System.Boolean":
                        result = GetBoolean(RealByteArray);
                        break;
                    case "System.Byte":
                        result = GetByte(RealByteArray);
                        break;
                    case "System.Single":
                        result = GetSingle(RealByteArray);
                        break;
                    case "System.Int16":
                        result = GetInt16(RealByteArray);
                        break;
                    case "System.Int32":
                        result = GetInt32(RealByteArray);
                        break;
                    case "System.UInt16":
                        result = GetUInt16(RealByteArray);
                        break;
                    case "System.UInt32":
                        result = GetUInt32(RealByteArray);
                        break;
                   
                    //数组变量
                    case "System.Byte[]":
                        result = GetByteArray(RealByteArray);
                        break;
                    case "System.Single[]":
                        result = GetSingleArray(RealByteArray);
                        break;
                    case "System.Int16[]":
                        result = GetInt16Array(RealByteArray);
                        break;
                    case "System.UInt16[]":
                        result = GetUInt16Array(RealByteArray);
                        break;
                    case "System.Int32[]":
                        result = GetInt32Array(RealByteArray);
                        break;
                    case "System.UInt32[]":
                        result = GetUInt32Array(RealByteArray);
                        break;

                }
                return (T)result;
            }
        }

        private object GetUInt32Array(byte[] realByteArray)
        {
            if (realByteArray.Length == 0)
            {
                throw new ArgumentException(realByteArray.Length + "字节数组长度为0");
            }
            if (realByteArray.Length != Command.Length * 4)
            {
                throw new ArgumentException(realByteArray.Length + "转换的UInt32[]长度不匹配");
            }
            uint[] result = new uint[realByteArray.Length / 4];//int占4个字节 4个字节转换为一个int
            switch (Command.DataType)
            {
                case CommunicationLib.Enums.DataType.WordHEX:
                    for (int i = 0; i < realByteArray.Length; i += 4)
                    {
                        //高低位转换
                        byte[] temp = new byte[4];
                        temp[0] = realByteArray[i + 1];
                        temp[1] = realByteArray[i];
                        temp[2] = realByteArray[i + 3];
                        temp[3] = realByteArray[i + 2];
                        uint number = BitConverter.ToUInt32(temp, 0);
                        result[i / 4] = number;//将转换后的int存入结果数组
                    }
                    break;
            }
            return result;
        }

        private object GetInt32Array(byte[] realByteArray)
        {
            if(realByteArray.Length == 0)
            {
                throw new ArgumentException(realByteArray.Length + "字节数组长度为0");
            }
            if(realByteArray.Length != Command.Length * 4)
            {
                throw new ArgumentException(realByteArray.Length + "转换的Int32[]长度不匹配");
            }
            int[] result = new int[realByteArray.Length / 4];//int占4个字节 4个字节转换为一个int
            switch (Command.DataType)
            {
                case CommunicationLib.Enums.DataType.WordHEX:
                    for (int i = 0; i < realByteArray.Length; i += 4)
                    {
                        //高低位转换
                        byte[] temp = new byte[4];
                        temp[0] = realByteArray[i + 1];
                        temp[1] = realByteArray[i];
                        temp[2] = realByteArray[i + 3];
                        temp[3] = realByteArray[i + 2];
                        int number = BitConverter.ToInt32(temp, 0);
                        result[i / 4] = number;//将转换后的int存入结果数组
                    }
                    break;
            }
            return result;
        }

        private object GetUInt16Array(byte[] realByteArray)
        {
            if (realByteArray.Length == 0)
            {
                throw new ArgumentException(realByteArray.Length + "字节数组长度为0");
            }
            if (realByteArray.Length != Command.Length * 2)
            {
                throw new ArgumentException(realByteArray.Length + "转换的UInt16[]长度不匹配");
            }
            ushort[] result = new ushort[Command.Length];//ushort占2个字节 2个字节转换为一个ushort
            switch (Command.DataType)
            {
                case CommunicationLib.Enums.DataType.WordHEX:
                    for (int i = 0; i < realByteArray.Length; i += 2)
                    {
                        result[i / 2] = (ushort)((realByteArray[i] << 8) | realByteArray[i + 1]);//高低位转换
                    }
                    break;
            }
            return result;
        }

        private object GetInt16Array(byte[] realByteArray)
        {
           if(realByteArray.Length == 0)
            {
                throw new ArgumentException(realByteArray.Length + "字节数组长度为0");
            }
            if(realByteArray.Length  != Command.Length * 2)
            {
                throw new ArgumentException(realByteArray.Length + "转换的Int16[]长度不匹配");
            }
            short[] result = new short[Command.Length];//short占2个字节 2个字节转换为一个short
            switch (Command.DataType)
            {
                case CommunicationLib.Enums.DataType.WordHEX:
                    for (int i = 0; i < realByteArray.Length; i+=2)
                    {
                        result[i/2] = (short)((realByteArray[i] << 8) | realByteArray[i + 1]);//高低位转换
                    }
                break;
            }
            return result;
        }

        private object GetSingleArray(byte[] realByteArray)
        {
            if (realByteArray.Length == 0)
            {
                throw new ArgumentException(realByteArray.Length + "字节数组长度为0");
            }
            if (realByteArray.Length != Command.Length * 2)
            {
                throw new ArgumentException(realByteArray.Length + "转换的float[]长度不匹配");
            }
            float[] result = new float[realByteArray.Length / 4];//float占4个字节 4个字节转换为一个float
            switch (Command.DataType)
            {
                case CommunicationLib.Enums.DataType.WordHEX:
                    for (int i = 0; i < realByteArray.Length; i += 4)
                    {
                        //高低位转换
                        byte[] temp = new byte[4];
                        temp[0] = realByteArray[i + 1];
                        temp[1] = realByteArray[i];
                        temp[2] = realByteArray[i + 3];
                        temp[3] = realByteArray[i + 2];
                        float number = BitConverter.ToSingle(temp, 0);
                        result[i / 4] = number;//将转换后的int存入结果数组
                    }
                    break;
            }
            return result;
        }

        private object GetByteArray(byte[] realByteArray)
        {
            return realByteArray;
        }

        private object GetUInt32(byte[] realByteArray)
        {
            if (realByteArray == null || realByteArray.Length != 4)
            {
                throw new ArgumentException("转换Int32需要4个字节");
            }
            //高低位转换
            for (int i = 0; i < realByteArray.Length; i++)
            {
                byte temp = realByteArray[i];
                realByteArray[i] = realByteArray[i + 1];
                realByteArray[i + 1] = temp;
            }
            //将字节数组转换为Int32
            return BitConverter.ToUInt32(realByteArray, 0);
        }

        private object GetUInt16(byte[] realByteArray)
        {
            if (realByteArray == null || realByteArray.Length != 2)
            {
                throw new ArgumentException("转换UInt16需要2个字节");
            }
            //高低位转换
            byte temp = realByteArray[0];
            realByteArray[0] = realByteArray[1];
            realByteArray[1] = temp;
            //将字节数组转换为UInt16
            return BitConverter.ToUInt16(realByteArray, 0);
        }

        private object GetInt32(byte[] realByteArray)
        {
          if(realByteArray == null || realByteArray.Length != 4)
            {
                throw new ArgumentException("转换Int32需要4个字节");
            }
            //高低位转换
            for (int i = 0; i < realByteArray.Length; i++)
            {
                byte temp = realByteArray[i];
                realByteArray[i] = realByteArray[i + 1];
                realByteArray[i + 1] = temp;
            }
            //将字节数组转换为Int32
            return BitConverter.ToInt32(realByteArray, 0);
        }

        private object GetInt16(byte[] realByteArray)
        {
            if(realByteArray == null || realByteArray.Length != 2)
            {
                throw new ArgumentException("转换Int16需要2个字节");
            }
            //高低位转换
            for (int i = 0; i < realByteArray.Length; i++)
            {
                byte temp = realByteArray[i];
                realByteArray[i] = realByteArray[i + 1];
                realByteArray[i + 1] = temp;
            }
            //将字节数组转换为Int16
            return BitConverter.ToInt16(realByteArray, 0);
        }

        private object GetSingle(byte[] realByteArray)
        {
            if (realByteArray.Length == 0)
            {
                throw new ArgumentException(realByteArray.Length + "字节数组长度为0");
            }
            if (realByteArray.Length != 4)
            {
                throw new ArgumentException(realByteArray.Length + "转换的float[]长度不匹配");
            }
                        //高低位转换
                        byte[] temp = new byte[4];
                        temp[0] = realByteArray[1];
                        temp[1] = realByteArray[0];
                        temp[2] = realByteArray[3];
                        temp[3] = realByteArray[2];
                        float number = BitConverter.ToSingle(temp, 0);
                       
           
            return number;
        }

        private object GetByte(byte[] realByteArray)
        {
            if (realByteArray.Length != 2)
            {
                throw new ArgumentException("Byte需要1个字节 ");
            }

            return realByteArray[1];
        }

        private object GetBoolean(byte[] realByteArray)
        {
            bool result = false;
            if (realByteArray == null || realByteArray.Length != 1)
            {
                throw new ArgumentException("转换Boolean需要1个字节");
            }
            if(Command.DataType == CommunicationLib.Enums.DataType.Bit)
            {
                result = realByteArray[0] != 0;
            }
            return result;
        }

        public byte[] RealByteArray
        {
            get
            {
                //如果接收缓冲区为空或者长度小于30，返回空数组
                if (ReceiveBuffer == null || ReceiveBuffer.Length < 30)
                {
                    return new byte[0];
                }
                //检查返回数据头46 49 4E 53
                if (ReceiveBuffer[0] != 0x46 || ReceiveBuffer[1] != 0x49 || ReceiveBuffer[2] != 0x4E || ReceiveBuffer[3] != 0x53)
                {
                    return new byte[0];
                }
                //判断指令错误码
                if (ReceiveBuffer[28] != 0x00 || ReceiveBuffer[29] != 0x00)
                {
                    return new byte[0];
                }
                //判断指令总长度
                if (ReceiveBuffer[7] + 8 != ReceiveBuffer.Length)
                {
                    return new byte[0];
                }
                //判断读写指令的回复数据
                if (ReceiveBuffer[26] != 0x01 || ReceiveBuffer[27] != 0x01)
                {
                    //截取数据部分
                    var length = ReceiveBuffer.Length - 30; // 30是前面的头部和错误码部分
                    var result = new byte[length];
                    Array.Copy(ReceiveBuffer, 30, result, 0, length);// 从ReceiveBuffer中第30个字节开始复制到result数组
                    return result;
                }
                else if (ReceiveBuffer[26] == 0x01 && ReceiveBuffer[27] == 0x02)
                {
                    //todo: 处理批量读取数据
                }
                return new byte[0];
            }
        }
        public bool Sucess { get; set; }

        public string Message { get; set; }

        public Exception Exception { get; set; }
        public byte[] ReceiveBuffer { get; set; }
        /// <summary>
        ///读取获取plc返回的数据部分
        /// </summary>
       
    }
}
